package cn.gok.springsecuritydemo01.config;


import cn.gok.springsecuritydemo01.authenticationHandler.LoginFailHandler;
import cn.gok.springsecuritydemo01.authenticationHandler.LoginSuccessHandler;
import cn.gok.springsecuritydemo01.authenticationHandler.MyLogoutHandler;
import cn.gok.springsecuritydemo01.authenticationHandler.MyLogoutSuccessHandler;
import cn.gok.springsecuritydemo01.service.MyUserDetailsService;
import cn.gok.springsecuritydemo01.service.MyUserDetailsService1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
    实现 WebSecurityConfigurerAdapter ，自定义验证逻辑
 */
@Configuration
public class MySpringSecurityConfigure extends WebSecurityConfigurerAdapter {

    //基于内存构建用户信息
//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        InMemoryUserDetailsManager imuds = new InMemoryUserDetailsManager();
//        User.UserBuilder builder = User.builder();
//        //空的权限集合
//        List<GrantedAuthority> authorities = new ArrayList<>();
//        builder.authorities(authorities);
//
//        builder.username("zhangsan");
//
//        // {noop}表示不要对密码进行加密操作
//        builder.password("{noop}123456");
//        UserDetails user1 = builder.build();
//
//        builder.username("lisi");
//        builder.password("{noop}1234568");
//        UserDetails user2 = builder.build();
//
//        builder.username("xiaoming");
//        builder.password("{noop}1234567");
//        UserDetails user3 = builder.build();
//
//        imuds.createUser(user1);
//        imuds.createUser(user2);
//        imuds.createUser(user3);
//        auth.userDetailsService(imuds);
//    }

    @Autowired
    private MyUserDetailsService myUserDetailsService;

    @Autowired
    private MyUserDetailsService1 myUserDetailsService1;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 使用自定义的UserDetailsService  从数据库获取用户信息
        auth.userDetailsService(myUserDetailsService1);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //放过静态资源
        web.ignoring().antMatchers("/css/**","/js/**","/images/**");
    }

    /**
     * 重写此方法进行自定义的验证配置
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //开启表单验证
                .formLogin()
                //指定登录页
                .loginPage("/toLoginPage")
                //指定处理登录请求的地址，默认为/login
                .loginProcessingUrl("/login")
                //指定登录页 ，用户名和密码的 属性名
                .passwordParameter("password")
                .usernameParameter("userName")

                //登录成功后，转发到指定的地址
//                .successForwardUrl("/index.html")
                //登录失败后，转发到指定的地址
//                .failureForwardUrl("/toFailPage")
                //指定自定义的 登录和失败的处理器
                .successHandler(new LoginSuccessHandler())
                .failureHandler(new LoginFailHandler())
                .and()
                //开启记住我功能
                .rememberMe()
                .tokenValiditySeconds(3600)
                // 使用自定义的代码，将remember-me功能产生的token存入 数据库中
                .tokenRepository(persistentTokenRepository())

                .and()
                .logout()
                //自定义退出登录的地址
                .logoutUrl("/logout")
                //指定自定义退出登录成功的处理器
                .logoutSuccessHandler(new MyLogoutSuccessHandler())
                //指定自定义退出登录处理器
                .addLogoutHandler(new MyLogoutHandler())

                .and()
                // 获取授权管理控制对象， Security所有的权限控制都基于这个类进行控制。
                .authorizeRequests()
                //login.html 被放过，不需要做验证， 需要注意： 放过的请求配置 一定要处于 所有请求都必须验证配置的最的上面
                .antMatchers("/toLoginPage","/user/addUser","/addUser.html").permitAll()
                //所有的请求
                .anyRequest()
                //进行验证
                .authenticated();

        // 关闭csrf防护
        http.csrf().disable();

        // 允许iframe加载页面
        http.headers().frameOptions().sameOrigin();
    }


    @Autowired
    private DataSource dataSource;
    /**
        记住我功能： 将服务器产生的token 存入数据库中
     */
    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        //设置数据源
        tokenRepository.setDataSource(dataSource);
        // 启动时创建一张表, 第一次启动的时候创建, 第二次启动的时候需要注释掉, 否则会报错
//        tokenRepository.setCreateTableOnStartup(true);
        return tokenRepository;
    }
}
